// src/utils/validation.rs

//! 数据验证工具

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use regex::Regex;
use chrono::{DateTime, Utc};

/// 验证规则
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationRule {
    /// 规则名称
    pub name: String,
    /// 规则类型
    pub rule_type: ValidationType,
    /// 字段路径
    pub field_path: String,
    /// 规则参数
    pub parameters: HashMap<String, serde_json::Value>,
    /// 错误消息
    pub error_message: String,
}

/// 验证类型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ValidationType {
    /// 必填验证
    Required,
    /// 长度验证
    Length,
    /// 正则表达式验证
    Regex,
    /// 数值范围验证
    NumericRange,
    /// 日期格式验证
    DateFormat,
    /// 邮箱格式验证
    Email,
    /// URL格式验证
    Url,
    /// 枚举值验证
    Enum,
    /// 自定义验证
    Custom,
}

/// 验证结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationResult {
    /// 是否验证通过
    pub is_valid: bool,
    /// 错误信息
    pub errors: Vec<ValidationError>,
    /// 警告信息
    pub warnings: Vec<ValidationWarning>,
}

/// Schema验证器
#[derive(Debug)]
pub struct SchemaValidator {
    rules: Vec<ValidationRule>,
}

impl SchemaValidator {
    /// 创建新的Schema验证器
    pub fn new() -> Self {
        Self {
            rules: Vec::new(),
        }
    }

    /// 添加验证规则
    pub fn add_rule(&mut self, rule: ValidationRule) {
        self.rules.push(rule);
    }

    /// 验证数据
    pub fn validate(&self, data: &serde_json::Value) -> ValidationResult {
        let mut result = ValidationResult {
            is_valid: true,
            errors: Vec::new(),
            warnings: Vec::new(),
        };

        // 简单验证逻辑
        for rule in &self.rules {
            // 实际验证逻辑会在这里实现
        }

        result
    }
}

impl Default for SchemaValidator {
    fn default() -> Self {
        Self::new()
    }
}

/// 验证错误
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationError {
    /// 字段路径
    pub field_path: String,
    /// 错误消息
    pub message: String,
    /// 错误代码
    pub code: String,
    /// 错误值
    pub value: Option<serde_json::Value>,
}

/// 验证警告
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ValidationWarning {
    /// 字段路径
    pub field_path: String,
    /// 警告消息
    pub message: String,
    /// 警告代码
    pub code: String,
    /// 警告值
    pub value: Option<serde_json::Value>,
}

/// 验证器
pub struct Validator {
    /// 验证规则
    rules: Vec<ValidationRule>,
    /// 正则表达式缓存
    regex_cache: HashMap<String, Regex>,
}

impl Validator {
    /// 创建新的验证器
    pub fn new() -> Self {
        Self {
            rules: Vec::new(),
            regex_cache: HashMap::new(),
        }
    }

    /// 添加验证规则
    pub fn add_rule(&mut self, rule: ValidationRule) {
        self.rules.push(rule);
    }

    /// 添加多个验证规则
    pub fn add_rules(&mut self, rules: Vec<ValidationRule>) {
        self.rules.extend(rules);
    }

    /// 验证数据
    pub fn validate<T>(&mut self, data: &T) -> ValidationResult
    where
        T: Serialize + std::fmt::Debug,
    {
        let mut result = ValidationResult {
            is_valid: true,
            errors: Vec::new(),
            warnings: Vec::new(),
        };

        let value = match serde_json::to_value(data) {
            Ok(v) => v,
            Err(e) => {
                result.is_valid = false;
                result.errors.push(ValidationError {
                    field_path: "root".to_string(),
                    message: format!("序列化失败: {}", e),
                    code: "SERIALIZATION_ERROR".to_string(),
                    value: None,
                });
                return result;
            }
        };

        let rules = self.rules.clone();
        for rule in &rules {
            if let Some(field_value) = self.get_field_value(&value, &rule.field_path) {
                let validation_result = self.validate_field(rule, &field_value);
                if !validation_result.is_valid {
                    result.is_valid = false;
                    result.errors.extend(validation_result.errors);
                }
                result.warnings.extend(validation_result.warnings);
            }
        }

        result
    }

    /// 验证单个字段
    fn validate_field(&mut self, rule: &ValidationRule, value: &serde_json::Value) -> ValidationResult {
        let mut result = ValidationResult {
            is_valid: true,
            errors: Vec::new(),
            warnings: Vec::new(),
        };

        match rule.rule_type {
            ValidationType::Required => {
                if value.is_null() {
                    result.is_valid = false;
                    result.errors.push(ValidationError {
                        field_path: rule.field_path.clone(),
                        message: rule.error_message.clone(),
                        code: "REQUIRED_FIELD".to_string(),
                        value: Some(value.clone()),
                    });
                }
            },
            ValidationType::Length => {
                if let Some(min_length) = rule.parameters.get("min_length").and_then(|v| v.as_u64()) {
                    if let Some(str_value) = value.as_str() {
                        if str_value.len() < min_length as usize {
                            result.is_valid = false;
                            result.errors.push(ValidationError {
                                field_path: rule.field_path.clone(),
                                message: format!("长度不能少于 {}", min_length),
                                code: "MIN_LENGTH".to_string(),
                                value: Some(value.clone()),
                            });
                        }
                    }
                }

                if let Some(max_length) = rule.parameters.get("max_length").and_then(|v| v.as_u64()) {
                    if let Some(str_value) = value.as_str() {
                        if str_value.len() > max_length as usize {
                            result.is_valid = false;
                            result.errors.push(ValidationError {
                                field_path: rule.field_path.clone(),
                                message: format!("长度不能超过 {}", max_length),
                                code: "MAX_LENGTH".to_string(),
                                value: Some(value.clone()),
                            });
                        }
                    }
                }
            }
            ValidationType::Regex => {
                    if let Some(pattern) = rule.parameters.get("pattern").and_then(|v| v.as_str()) {
                        let regex = match self.get_or_create_regex(pattern) {
                            Ok(re) => re,
                            Err(e) => {
                                result.is_valid = false;
                                result.errors.push(ValidationError {
                                    field_path: rule.field_path.clone(),
                                    message: format!("正则表达式错误: {}", e),
                                    code: "REGEX_ERROR".to_string(),
                                    value: Some(value.clone()),
                                });
                                return result;
                            }
                        };

                        if let Some(str_value) = value.as_str() {
                            if !regex.is_match(str_value) {
                                result.is_valid = false;
                                result.errors.push(ValidationError {
                                    field_path: rule.field_path.clone(),
                                    message: rule.error_message.clone(),
                                    code: "REGEX_MISMATCH".to_string(),
                                    value: Some(value.clone()),
                                });
                            }
                        }
                    }
                }
                ValidationType::NumericRange => {
                    if let Some(num_value) = value.as_f64() {
                        if let Some(min_value) = rule.parameters.get("min").and_then(|v| v.as_f64()) {
                            if num_value < min_value {
                                result.is_valid = false;
                                result.errors.push(ValidationError {
                                    field_path: rule.field_path.clone(),
                                    message: format!("数值不能小于 {}", min_value),
                                    code: "MIN_VALUE".to_string(),
                                    value: Some(value.clone()),
                                });
                            }
                        }

                        if let Some(max_value) = rule.parameters.get("max").and_then(|v| v.as_f64()) {
                            if num_value > max_value {
                                result.is_valid = false;
                                result.errors.push(ValidationError {
                                    field_path: rule.field_path.clone(),
                                    message: format!("数值不能大于 {}", max_value),
                                    code: "MAX_VALUE".to_string(),
                                    value: Some(value.clone()),
                                });
                            }
                        }
                    }
                },
                ValidationType::DateFormat => {
                    if let Some(format) = rule.parameters.get("format").and_then(|v| v.as_str()) {
                        if let Some(str_value) = value.as_str() {
                            match format {
                                "rfc3339" => {
                                    match DateTime::parse_from_rfc3339(str_value) {
                                        Ok(_) => {},
                                        Err(e) => {
                                            result.is_valid = false;
                                            result.errors.push(ValidationError {
                                                field_path: rule.field_path.clone(),
                                                message: format!("日期格式错误: {}", e),
                                                code: "DATE_FORMAT_ERROR".to_string(),
                                                value: Some(value.clone()),
                                            });
                                        }
                                    }
                                },
                                "iso8601" => {
                                    match DateTime::parse_from_rfc3339(str_value) {
                                        Ok(_) => {},
                                        Err(e) => {
                                            result.is_valid = false;
                                            result.errors.push(ValidationError {
                                                field_path: rule.field_path.clone(),
                                                message: format!("日期格式错误: {}", e),
                                                code: "DATE_FORMAT_ERROR".to_string(),
                                                value: Some(value.clone()),
                                            });
                                        }
                                    }
                                },
                                _ => {
                                    // 默认尝试多种格式
                                    if DateTime::parse_from_rfc3339(str_value).is_err()
                                        && DateTime::parse_from_str(str_value, "%Y-%m-%d %H:%M:%S").is_err() {
                                        result.is_valid = false;
                                        result.errors.push(ValidationError {
                                            field_path: rule.field_path.clone(),
                                            message: "日期格式错误".to_string(),
                                            code: "DATE_FORMAT_ERROR".to_string(),
                                            value: Some(value.clone()),
                                        });
                                    }
                                }
                            }
                        }
                    }
                },
                ValidationType::Email => {
                    if let Some(str_value) = value.as_str() {
                        let email_regex = self.get_or_create_regex(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
                        if !email_regex.is_match(str_value) {
                            result.is_valid = false;
                            result.errors.push(ValidationError {
                                field_path: rule.field_path.clone(),
                                message: "邮箱格式错误".to_string(),
                                code: "EMAIL_FORMAT_ERROR".to_string(),
                                value: Some(value.clone()),
                            });
                        }
                    }
                },
                ValidationType::Url => {
                    if let Some(str_value) = value.as_str() {
                        match url::Url::parse(str_value) {
                            Ok(_) => {},
                            Err(e) => {
                                result.is_valid = false;
                                result.errors.push(ValidationError {
                                    field_path: rule.field_path.clone(),
                                    message: format!("URL格式错误: {}", e),
                                    code: "URL_FORMAT_ERROR".to_string(),
                                    value: Some(value.clone()),
                                });
                            }
                        }
                    }
                },
                ValidationType::Enum => {
                    if let Some(allowed_values) = rule.parameters.get("allowed_values").and_then(|v| v.as_array()) {
                        if let Some(str_value) = value.as_str() {
                            let is_valid = allowed_values.iter()
                                .any(|v| v.as_str() == Some(str_value));

                            if !is_valid {
                                let allowed: Vec<String> = allowed_values.iter()
                                    .filter_map(|v| v.as_str().map(|s| s.to_string()))
                                    .collect();

                                result.is_valid = false;
                                result.errors.push(ValidationError {
                                    field_path: rule.field_path.clone(),
                                    message: format!("枚举值错误，允许的值: {:?}", allowed),
                                    code: "ENUM_VALUE_ERROR".to_string(),
                                    value: Some(value.clone()),
                                });
                            }
                        }
                    }
                },
                ValidationType::Custom => {
                    // 自定义验证逻辑
                    // 这里可以根据具体的业务需求实现
                },
            }

        result
    }

    /// 从值中获取指定路径的字段值
    fn get_field_value(&self, value: &serde_json::Value, path: &str) -> Option<serde_json::Value> {
        let parts: Vec<&str> = path.split('.').collect();
        let mut current = value;

        for part in parts {
            match current {
                serde_json::Value::Object(map) => {
                    if let Some(field_value) = map.get(part) {
                        current = field_value;
                    } else {
                        return None;
                    }
                },
                serde_json::Value::Array(arr) => {
                    if let Ok(index) = part.parse::<usize>() {
                        if let Some(item) = arr.get(index) {
                            current = item;
                        } else {
                            return None;
                        }
                    } else {
                        return None;
                    }
                },
                _ => return Some(current.clone()),
            }
        }

        Some(current.clone())
    }

    /// 获取或创建正则表达式
    fn get_or_create_regex(&mut self, pattern: &str) -> Result<Regex, regex::Error> {
        if let Some(regex) = self.regex_cache.get(pattern) {
            Ok(regex.clone())
        } else {
            let regex = Regex::new(pattern)?;
            self.regex_cache.insert(pattern.to_string(), regex.clone());
            Ok(regex)
        }
    }
}

impl Default for Validator {
    fn default() -> Self {
        Self::new()
    }
}

/// 便捷的验证器构建器
pub struct ValidatorBuilder {
    validator: Validator,
}

impl ValidatorBuilder {
    pub fn new() -> Self {
        Self {
            validator: Validator::new(),
        }
    }

    /// 添加必填验证
    pub fn required(mut self, field_path: &str, error_message: &str) -> Self {
        self.validator.add_rule(ValidationRule {
            name: format!("required_{}", field_path.replace('.', "_")),
            rule_type: ValidationType::Required,
            field_path: field_path.to_string(),
            parameters: HashMap::new(),
            error_message: error_message.to_string(),
        });
        self
    }

    /// 添加长度验证
    pub fn length(mut self, field_path: &str, min: Option<u64>, max: Option<u64>, error_message: &str) -> Self {
        let mut parameters = HashMap::new();
        if let Some(min_val) = min {
            parameters.insert("min_length".to_string(), serde_json::Value::Number(serde_json::Number::from(min_val as i64)));
        }
        if let Some(max_val) = max {
            parameters.insert("max_length".to_string(), serde_json::Value::Number(serde_json::Number::from(max_val as i64)));
        }

        self.validator.add_rule(ValidationRule {
            name: format!("length_{}", field_path.replace('.', "_")),
            rule_type: ValidationType::Length,
            field_path: field_path.to_string(),
            parameters,
            error_message: error_message.to_string(),
        });
        self
    }

    /// 添加正则验证
    pub fn regex(mut self, field_path: &str, pattern: &str, error_message: &str) -> Self {
        let mut parameters = HashMap::new();
        parameters.insert("pattern".to_string(), serde_json::Value::String(pattern.to_string()));

        self.validator.add_rule(ValidationRule {
            name: format!("regex_{}", field_path.replace('.', "_")),
            rule_type: ValidationType::Regex,
            field_path: field_path.to_string(),
            parameters,
            error_message: error_message.to_string(),
        });
        self
    }

    /// 添加数值范围验证
    pub fn numeric_range(mut self, field_path: &str, min: Option<f64>, max: Option<f64>, error_message: &str) -> Self {
        let mut parameters = HashMap::new();
        if let Some(min_val) = min {
            parameters.insert("min".to_string(), serde_json::Value::Number(serde_json::Number::from(min_val as i64)));
        }
        if let Some(max_val) = max {
            parameters.insert("max".to_string(), serde_json::Value::Number(serde_json::Number::from(max_val as i64)));
        }

        self.validator.add_rule(ValidationRule {
            name: format!("range_{}", field_path.replace('.', "_")),
            rule_type: ValidationType::NumericRange,
            field_path: field_path.to_string(),
            parameters,
            error_message: error_message.to_string(),
        });
        self
    }

    /// 构建验证器
    pub fn build(self) -> Validator {
        self.validator
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_validator_required() {
        let mut validator = Validator::new();
        validator.add_rule(ValidationRule {
            name: "test_required".to_string(),
            rule_type: ValidationType::Required,
            field_path: "name".to_string(),
            parameters: HashMap::new(),
            error_message: "姓名不能为空".to_string(),
        });

        let data = serde_json::json!({
            "name": "测试"
        });

        let result = validator.validate(&data);
        assert!(result.is_valid);
        assert!(result.errors.is_empty());
    }

    #[test]
    fn test_validator_length() {
        let validator = ValidatorBuilder::new()
            .length("name", Some(1), Some(10), "姓名长度必须在1-10个字符之间")
            .build();

        let data = serde_json::json!({
            "name": "测试"
        });

        let result = validator.validate(&data);
        assert!(result.is_valid);
        assert!(result.errors.is_empty());
    }

    #[test]
    fn test_validator_email() {
        let validator = ValidatorBuilder::new()
            .regex("email", r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", "邮箱格式不正确")
            .build();

        let valid_data = serde_json::json!({
            "email": "test@example.com"
        });

        let invalid_data = serde_json::json!({
            "email": "invalid-email"
        });

        let valid_result = validator.validate(&valid_data);
        assert!(valid_result.is_valid);

        let invalid_result = validator.validate(&invalid_data);
        assert!(!invalid_result.is_valid);
        assert!(!invalid_result.errors.is_empty());
    }
}